#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>

#define DUMPBUFFER_INIT_SIZE		8
#define DUMPBUFFER_MAX_DOUBLE_SIZE	1024*1024

int CreateDumpBuffer( char **pp_buf , int *p_buf_size , int *p_buf_len )
{
	(*p_buf_size) = DUMPBUFFER_INIT_SIZE ;
	if( pp_buf == NULL )
		return -1;
	(*pp_buf) = (char *)malloc( (*p_buf_size) ) ;
	if( (*pp_buf) == NULL )
		return -2;
	(*p_buf_len) = 0 ;
	
	return 0;
}

int ResizeDumpBuffer( char **pp_buf , int *p_buf_size )
{
	int	new_buf_size ;
	char	*new_buf = NULL ;
	
	if( (*p_buf_size) <= DUMPBUFFER_MAX_DOUBLE_SIZE )
		new_buf_size = (*p_buf_size) * 2 ;
	else
		new_buf_size = (*p_buf_size) + DUMPBUFFER_MAX_DOUBLE_SIZE ;
	new_buf = (char *)realloc( (*pp_buf) , new_buf_size ) ;
	if( new_buf == NULL )
		return -1;
	(*pp_buf) = new_buf ;
	(*p_buf_size) = new_buf_size ;
	
	return 0;
}

int AppendDumpBuffer( char **pp_buf , int *p_buf_size , int *p_buf_len , char *format , ... )
{
	va_list		valist ;
	va_list		valist_copy ;
	int		len ;
	int		nret = 0 ;
	
	va_start( valist , format );
	va_copy( valist_copy , valist );
_REDO :
	len = vsnprintf( (*pp_buf)+(*p_buf_len) , (*p_buf_size)-(*p_buf_len)-1 , format , valist ) ;
	va_end( valist );
#if ( defined _WIN32 )
	if( len == -1 || len >= (*p_buf_size)-(*p_buf_len)-1 )
#elif ( defined __linux__ ) || ( defined _AIX )
	if( len >= (*p_buf_size)-(*p_buf_len)-1 )
#endif
	{
		nret = ResizeDumpBuffer( pp_buf , p_buf_size ) ;
		if( nret )
			return nret;
		
		va_copy( valist , valist_copy );
		goto _REDO;
	}
	
	(*p_buf_len) += len ;
	*((*pp_buf)+(*p_buf_len)) = '\0' ;
	
	return 0;
}

